package tr.edu.ege.kipler.satisfiability.completion;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import tr.edu.ege.kipler.satisfiability.ReasonerException;
import tr.edu.ege.kipler.satisfiability.Reasoner;
import tr.edu.ege.kipler.satisfiability.completion.rules.CompletionRule;
import tr.edu.ege.kipler.satisfiability.completion.rules.EmptyDomainRule;
import tr.edu.ege.kipler.satisfiability.completion.rules.dl.ABoxRule;
import tr.edu.ege.kipler.satisfiability.completion.rules.dl.NegatedConceptDefinitionRule;
import tr.edu.ege.kipler.satisfiability.container.ABox;
import tr.edu.ege.kipler.satisfiability.container.Individual;
import tr.edu.ege.kipler.satisfiability.container.ModifiedIndividualCollection;
import tr.edu.ege.kipler.satisfiability.container.WcsData;
import tr.edu.ege.kipler.satisfiability.container.World;
import tr.edu.ege.kipler.satisfiability.container.WorldConstraintSystem;

/**
 * 
 * @author İnanç Seylan
 *
 */
public class ModifiedIndividualBasedCompletionStrategy implements
		CompletionStrategy {
	private Reasoner reasoner;

	private List<ABoxRule> ruleList;

	private Comparator<Individual> comparator;

	public List<ABoxRule> getRuleList() {
		return ruleList;
	}

	public void setRuleList(List<ABoxRule> ruleList) {
		this.ruleList = ruleList;
	}

	public Reasoner getReasoner() {
		return reasoner;
	}

	public void setReasoner(Reasoner reasoner) {
		this.reasoner = reasoner;
	}

	public Comparator<Individual> getComparator() {
		return comparator;
	}

	public void setComparator(Comparator<Individual> comparator) {
		this.comparator = comparator;
	}

	public void apply(WorldConstraintSystem currentWcs) throws ReasonerException {
		World currentWorld = currentWcs.getAllWorlds().iterator().next();
		boolean ruleApplied;
		CompletionRule compRule = new NegatedConceptDefinitionRule(currentWcs,
				currentWorld);
		compRule.apply();
		compRule = new EmptyDomainRule(currentWcs, currentWorld);
		compRule.apply();
		do {
			ruleApplied = false;
			Iterator<Individual> indvIter = getIndividualList(currentWorld)
					.iterator();
			while (indvIter.hasNext() && !ruleApplied) {
				Individual indv = indvIter.next();
				Iterator<ABoxRule> ruleIter = getRuleList().iterator();
				while (ruleIter.hasNext() && !ruleApplied) {
					ABoxRule rule = ruleIter.next();
					rule.setWcs(currentWcs);
					rule.setWorld(currentWorld);
					rule.setIndividual(indv);
					rule.apply();
					ruleApplied = ruleApplied || rule.isApplied();
				}
				if (!ruleApplied) {
					WcsData wcsData = currentWcs.getData();
					wcsData.getModifiedIndividuals().remove(
							currentWorld.getName(), indv.getName());
				}
			}
		} while (ruleApplied);
	}

	private List<Individual> getIndividualList(World world) {
		Set<Individual> returnIndividuals = new HashSet<Individual>();
		Set<String> removeIndividuals = new HashSet<String>();
		ModifiedIndividualCollection todoList = world.getWcs().getData()
				.getModifiedIndividuals();
		for (Iterator<String> i = todoList.get(world.getName()).iterator(); i
				.hasNext();) {
			String indvName = i.next();
			ABox abox = world.getABox();
			if (abox.contains(indvName)) {
				Individual indv = abox.getIndividual(indvName);
				returnIndividuals.add(indv);
				Iterator<Individual> indvIter = abox.neighborIterator(indv);
				while (indvIter.hasNext()) {
					returnIndividuals.add(indvIter.next());
				}
			} else {
				removeIndividuals.add(indvName);
			}
		}
		for (String indvName : removeIndividuals) {
			todoList.remove(world.getName(), indvName);
		}
		List<Individual> result = new ArrayList<Individual>(returnIndividuals);
		Collections.sort(result, getComparator());
		return result;
	}

}
